#include "include.h"

_MB_DEVCOMOUT_T MB_DevComOut;


void MeBsp_DevComOut_DMA_Init(void)
{
  dma_init_type dma_init_struct;
  
  /* enable dma2 periph clock */
  crm_periph_clock_enable(CRM_DMA2_PERIPH_CLOCK, TRUE);
  
  dma_reset(DMA2_CHANNEL4);
  dma_default_para_init(&dma_init_struct);
  dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
  dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
  dma_init_struct.memory_inc_enable = TRUE;
  dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
  dma_init_struct.peripheral_inc_enable = FALSE;
  dma_init_struct.priority = DMA_PRIORITY_HIGH;
  dma_init_struct.loop_mode_enable = FALSE;
  dma_init(DMA2_CHANNEL4, &dma_init_struct);
  dma_interrupt_enable(DMA2_CHANNEL4,DMA_FDT_INT,TRUE);
  /* flexible function enable */
  dma_flexible_config(DMA2, FLEX_CHANNEL4, DMA_FLEXIBLE_UART3_RX);
  
  dma_reset(DMA2_CHANNEL5);
  dma_default_para_init(&dma_init_struct);
  dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
  dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
  dma_init_struct.memory_inc_enable = TRUE;
  dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
  dma_init_struct.peripheral_inc_enable = FALSE;
  dma_init_struct.priority = DMA_PRIORITY_HIGH;
  dma_init_struct.loop_mode_enable = TRUE;
  dma_init(DMA2_CHANNEL5, &dma_init_struct);
  dma_interrupt_enable(DMA2_CHANNEL5,DMA_FDT_INT,TRUE);
  /* flexible function enable */
  dma_flexible_config(DMA2, FLEX_CHANNEL5, DMA_FLEXIBLE_UART3_TX);
  
  // DMA2_CHANNEL4->dtcnt = 100;
   DMA2_CHANNEL4->paddr = (uint32_t)&USART3->dt;
  // DMA2_CHANNEL4->maddr = (uint32_t)MB_DevComOut.cRxBuff;
  
  // DMA2_CHANNEL5->dtcnt = 100;
   DMA2_CHANNEL5->paddr = (uint32_t)&USART3->dt;
  // DMA2_CHANNEL5->maddr = (uint32_t)MB_DevComOut.cTxBuff;
  
  dma_channel_enable(DMA2_CHANNEL4, FALSE);
  dma_channel_enable(DMA2_CHANNEL5, FALSE);
}

void MeBsp_DevComOut_Init(void)
{
  gpio_init_type gpio_init_struct;
  
  /* enable usart3 periph clock */
  crm_periph_clock_enable(CRM_USART3_PERIPH_CLOCK, TRUE);
  /* enable gpiob periph clock */
  crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
  
  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);

  nvic_irq_enable(USART3_IRQn, 0, 1);
  nvic_irq_enable(DMA2_Channel4_5_IRQn, 0, 1);
  
  MeBsp_DevComOut_DMA_Init();
  
  gpio_default_para_init(&gpio_init_struct);

  /* configure the TX pin */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_pins = GPIO_PINS_10;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(GPIOB, &gpio_init_struct);

  /* configure the RX pin */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
  gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
  gpio_init_struct.gpio_pins = GPIO_PINS_11;
  gpio_init_struct.gpio_pull = GPIO_PULL_UP;
  gpio_init(GPIOB, &gpio_init_struct);

  /* configure param */
  usart_init(USART3, 250000, USART_DATA_8BITS, USART_STOP_2_BIT);
  usart_transmitter_enable(USART3, TRUE);
  usart_receiver_enable(USART3, TRUE);
  usart_parity_selection_config(USART3, USART_PARITY_NONE);

  usart_dma_transmitter_enable(USART3, TRUE);

  usart_dma_receiver_enable(USART3, TRUE);

  usart_hardware_flow_control_set(USART3, USART_HARDWARE_FLOW_NONE);

  usart_enable(USART3, TRUE);
  
  usart_interrupt_enable(USART3,USART_RDBF_INT,TRUE); //使能接收中断
  // USART3->ctrl1_bit.idleien = TRUE;

  memset(&MB_DevComOut, 0, sizeof(MB_DevComOut));
  memset(&MB_DevComOut_Data, 0, sizeof(MB_DevComOut_Data));
  memset(&MB_DevComOutRep_Data, 0, sizeof(MB_DevComOutRep_Data));
  
  USER_Debug_Out("--DevComOut Init\r\n");
}

void MeBsp_DevCom_Out_DMATransmitStart(void)
{
  DMA2_CHANNEL5->ctrl_bit.chen = FALSE;
  DMA2_CHANNEL5->maddr = (uint32_t )MB_DevComOut.pTransmitBuff;
  DMA2_CHANNEL5->dtcnt = MB_DevComOut.wTransmitLength;
  DMA2_CHANNEL5->ctrl_bit.chen = TRUE;
}

void MeBsp_DevCom_Out_TransmitBuff(uint8_t *p, uint16_t length)
{
  MB_DevComOut.cTransmitlineState = MB_DEVCOM_OUT_LINE_SEND_START;
  MB_DevComOut.wTransmitLength = length;
  MB_DevComOut.pTransmitBuff = p;
  MB_DevComOut.wTransmitCount = 0;
  
  usart_interrupt_enable(USART3,USART_TDC_INT,TRUE); //使能发送中断
  USART3->dt = 0xAA;
}

void MeBsp_DevCom_Out_DMAReciveStart(void)
{
  dma_flag_clear(DMA2_FDT4_FLAG); 
  usart_interrupt_enable(USART3,USART_RDBF_INT,FALSE); //关闭接收中断
  usart_interrupt_enable(USART3,USART_IDLE_INT,TRUE); //开启空闲中断
  DMA2_CHANNEL4->ctrl_bit.chen = FALSE;
  DMA2_CHANNEL4->maddr = (uint32_t )&MB_DevComOutRep_Data.buffer[0];
  DMA2_CHANNEL4->dtcnt = sizeof(MB_DevComOutRep_Data);
  USART3->ctrl3_bit.dmaren = TRUE;
  DMA2_CHANNEL4->ctrl_bit.chen = TRUE;
  MB_DevComOut.bRecvOKFlag = 1;
}

void MeBsp_DevCom_Out_DMAReciveStop(void)
{
  MB_DevComOut.wRecvLengthVal = sizeof(MB_DevComOutRep_Data) - DMA2_CHANNEL4->dtcnt;
  DMA2_CHANNEL4->ctrl_bit.chen = FALSE;
  dma_flag_clear(DMA2_FDT4_FLAG);
  USART3->ctrl3_bit.dmaren = FALSE;
  usart_interrupt_enable(USART3,USART_RDBF_INT,TRUE); //开启接收中断
  usart_interrupt_enable(USART3,USART_IDLE_INT,FALSE); //关闭空闲中断

  MB_DevComOut.cRecvLineState = MB_DEVCOM_OUT_LINE_RECV_IDLE;
}

void DMA2_Channel4_5_IRQHandler(void)
{
  if(dma_interrupt_flag_get(DMA2_FDT4_FLAG) != RESET) {
    MeBsp_DevCom_Out_DMAReciveStop();
    DMA2_CHANNEL4->ctrl_bit.chen = FALSE;
    dma_flag_clear(DMA2_FDT4_FLAG);
  }

  if(dma_interrupt_flag_get(DMA2_FDT5_FLAG) != RESET) {
    
    MB_DevComOut.wTransmitCount = MB_DevComOut.wTransmitLength;
		//此时DMA还没发送完数据,所以打开发送完成中断继续发数据
    usart_interrupt_enable(USART3,USART_TDC_INT,TRUE); //使能发送中断
    DMA2_CHANNEL5->ctrl_bit.chen = FALSE;
    dma_flag_clear(DMA2_FDT5_FLAG);
  }
}

void USART3_IRQHandler(void)
{
  uint8_t rev_buff;
  if((USART3->ctrl1_bit.rdbfien == SET ) && (USART3->sts & USART_RDBF_FLAG)) {
    rev_buff = USART3->dt;
    if ( (rev_buff == 0xAA) && ( MB_DevComOut.cRecvLineState == MB_DEVCOM_OUT_LINE_RECV_IDLE ) ) {
      MB_DevComOut.cRecvLineState = MB_DEVCOM_OUT_LINE_RECV_NORMAL;
      MeBsp_DevCom_Out_DMAReciveStart();
    }
  }

  if((USART3->ctrl1_bit.idleien == SET ) && (USART3->sts & USART_IDLEF_FLAG)) {
    usart_flag_clear(USART3,USART_IDLEF_FLAG);//
    rev_buff = USART3->dt;
    MeBsp_DevCom_Out_DMAReciveStop();
  }

  if((USART3->ctrl1_bit.tdcien == SET ) && (USART3->sts & USART_TDC_FLAG)) {
    usart_flag_clear(USART3,USART_TDC_FLAG);//
    if ( MB_DevComOut.wTransmitCount == 0 ) {
      usart_interrupt_enable(USART3,USART_TDC_INT,FALSE); //关闭发送中断
      MB_DevComOut.wTransmitCount = MB_DevComOut.wTransmitLength;
      MeBsp_DevCom_Out_DMATransmitStart();
    }
    else {
      usart_interrupt_enable(USART3,USART_TDC_INT,FALSE); //使能发送中断
      MB_DevComOut.cTransmitlineState = MB_DEVCOM_OUT_LINE_SEND_IDLE; //发送完成
      MB_DevComOut.wTransmitDelayCnt = 1;
    }
	}
}

void MeBsp_DevComOut_Send(void)
{
  uint8_t val;
  uint16_t length;
  if ( (MB_DevComOut.cTransmitlineState == MB_DEVCOM_OUT_LINE_SEND_IDLE) && (!MB_DevComOut.wTransmitDelayCnt) ) {
    val = MB_DevComIn_Data.packet.cLedNumVal;
    if ( val ) {
      val -= 1;
    }
    if ( MB_DevComIn.bRecvIsConnFlag && ( val ) ) {
      length = MB_DEVCOM_PACK_MIN_LENGTH + val*12;
      memcpy(&MB_DevComOut_Data,&MB_DevComIn_Data,length);
      MB_DevComOut_Data.packet.cLedNumVal = val;
      MB_DevComOut.wTransmitErrTimeCnt = 0;
      MeBsp_DevCom_Out_TransmitBuff((uint8_t *)&MB_DevComOut_Data,length);
    }
  }
  else {
    if ( MB_DevComOut.wTransmitErrTimeCnt < 200 ) { //100us*num
      MB_DevComOut.wTransmitErrTimeCnt++;
    }
    else {
      MB_DevComOut.cTransmitlineState = MB_DEVCOM_IN_LINE_SEND_IDLE;
      MB_DevComOut.wTransmitErrTimeCnt = 0;
    }
  }
  if ( MB_DevComOut.wTransmitDelayCnt ) {
    MB_DevComOut.wTransmitDelayCnt--;
  }
}

void MeBsp_DevComOut_Hanl(void)
{
  if ( MB_DevComOut.bRecvOKFlag ) {
    MB_DevComOut.bRecvOKFlag = 0;
    MB_DevComOut.wRecvErrOutTimeCnt = 20;
    MB_DevComOut.bRecvIsConnFlag = 1;
  }
  else {
    if ( MB_DevComOut.wRecvErrOutTimeCnt ) {
      MB_DevComOut.wRecvErrOutTimeCnt--;
    }
    else {
      MB_DevComOut.bRecvIsConnFlag = 0;
    }
  }
}
